package com.biwin.module.security.starter.handler;

import cn.hutool.json.JSONUtil;
import com.biwin.common.app.enums.BwSecurityExceptionEnum;
import com.biwin.common.app.vo.BwResponse;
import com.biwin.core.main.property.BiWinLoginProperties;
import com.biwin.module.jwt.api.exception.TokenAuthenticationException;
import com.biwin.module.org.api.service.ISystemUserService;
import com.biwin.module.org.api.vo.SystemUserVo;
import com.biwin.module.security.api.properties.BiWinSecurityProperties;
import com.biwin.module.security.starter.exception.BiWinFirstLoginAuthenticationException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.*;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

/**
 * TODO
 *
 * @author biwin
 * @since 0.0.1
 */
@Component
public class BwAuthenticationFailureHandler implements AuthenticationFailureHandler {

    private static final Log log = LogFactory.getLog(BwAuthenticationFailureHandler.class);

    @Autowired
    private ISystemUserService systemUserService;

    @Autowired
    private BiWinLoginProperties loginProperties;

    @Autowired
    private BiWinSecurityProperties securityProperties;

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
                                        AuthenticationException exception) throws IOException, ServletException {
        //返回json数据
        BwResponse bwResponse = null;
        if (exception instanceof AccountExpiredException) {
            //账号过期
            bwResponse = BwResponse.response(BwSecurityExceptionEnum.USER_ACCOUNT_EXPIRED);
        } else if (exception instanceof BadCredentialsException) {
            //密码错误
            bwResponse = BwResponse.response(BwSecurityExceptionEnum.USER_CREDENTIALS_ERROR);
            SystemUserVo systemUserVo =
                    systemUserService.findByAccount(request.getParameter(loginProperties.getUsername()));
            if (Objects.nonNull(systemUserVo)) {
                int passwordFaultNum = systemUserVo.getPasswordFaultNum() + 1;
                systemUserService.updatePasswordFaultNum(systemUserVo.getId(), passwordFaultNum);
                if (securityProperties.getPasswordMaxFailNumber() > 0 && passwordFaultNum >=
                        securityProperties.getPasswordMaxFailNumber()) {
                    systemUserService.lock(systemUserVo.getId());
                }
            }
        } else if (exception instanceof CredentialsExpiredException) {
            //密码过期
            bwResponse = BwResponse.response(BwSecurityExceptionEnum.USER_CREDENTIALS_EXPIRED);
        } else if (exception instanceof DisabledException) {
            //账号不可用
            bwResponse = BwResponse.response(BwSecurityExceptionEnum.USER_ACCOUNT_DISABLE);
        } else if (exception instanceof LockedException) {
            //账号锁定
            bwResponse = BwResponse.response(BwSecurityExceptionEnum.USER_ACCOUNT_LOCKED);
        } else if (exception instanceof InternalAuthenticationServiceException) {
            //用户不存在
            bwResponse = BwResponse.response(BwSecurityExceptionEnum.USER_ACCOUNT_NOT_EXIST);
        } else if (exception instanceof BiWinFirstLoginAuthenticationException) {
            // 用户首次登陆
            bwResponse = BwResponse.FAILED(exception.getMessage());
        } else if (exception instanceof TokenAuthenticationException) {
            // token 非法
            bwResponse = BwResponse.FAILED(exception.getMessage());
        } else {
            //其他错误
            bwResponse = BwResponse.FAILED(exception.getMessage());
        }

        response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
        response.setContentType("text/json;charset=utf-8");
        response.getWriter().write(JSONUtil.toJsonStr(bwResponse));
    }

}
